// void, Obj me

Unit  this;
Obj o;
point pt;
str names, TerrainBonus;
int bc, csc, disease_cost, time = 19000;
int per_health, per_stamina, min, range, i, k, j;
bool  bSleeped, sneakMode, possibleSpeed; 
ObjList olBall;

Sleep(rand(100)+50);

this = me.AsUnit();

bc = GetConst("BallCircle");
csc = GetConst("CurseStaminaCost");
disease_cost = GetConst("DiseaseCost");

if(.IsValid) // leave parry mode at new command
	.SetParryMode(false);
j = rand(800);
while(!.Stop(1000));

pt = .posRH;
	
.SetVisible(true);
.SetLastAttackTime();
//pr("stand_position dziala");  
possibleSpeed = false;
if(.IsValid){
	if(.IsMilitary()){
		if(!.IsHeirOf("Hero")
		&& !.IsHeirOf("Horse")
		&& !.IsHeirOf("RangedHorse")
		&& !.IsHeirOf("RamUnit")
		&& !.IsHeirOf("Sentry")
		&& !.HasFreedom){
			possibleSpeed = true;
		}
	}
}
while(.IsAlive){
	if(.CmdCount() > 1) break;
	//pr("idle: while: "+GetTime()/1000);	
	if(.HasSpecial(sneak)){
		if(!.InHolder){
			if(.IsVisible){
				if(!.EnemiesInSight()){
					if(time > 9000) if(EnvReadString(.player, "Camouflage") == "researched")
						time = 9000;
						
					if(.TimeWithoutAttack >= time+rand(1000))
						.SetVisible(false);
				}
			}
		}
	}
	
	sneakMode = false;  
	
	if(.hero.IsValid){
	
		names = "/1/Sneakmode/"+.hero.name;
		
		if(EnvReadString(names) != "yes") { 
			sneakMode = true;
			//pr("sneakMode true");
		}
		if(possibleSpeed)
			if(.speed_factor < 100)                                  
				.SetSpeedFactor(100);
				
		if(!.HasItem("Terrain bonus I") && 
		   !.HasItem("Terrain bonus II") &&
		   !.HasItem("Terrain bonus III") &&
		   !.HasItem("Terrain bonus IV")){
			if(GetTerrainHeight(.posRH) > 200 && GetTerrainHeight(.posRH) < 250)
				TerrainBonus = "Terrain bonus III";
			else if(GetTerrainHeight(.posRH) > 250)
				TerrainBonus = "Terrain bonus IV";
				
			if(TerrainBonus != ""){		
			
				if(.item_count < .max_items){
					.AddItem(TerrainBonus);
				} else {
					Item item;
					
					item = .GetItem(.max_items);
					
					if(item.IsValid)
						.ExchangeItem(item, TerrainBonus); 
				}
			}
		}
	}
	if(.IsRanged){
		if(.IsHeirOf("EChariot") && .stamina >= disease_cost){
			o = .BestTargetInSquadSight_PreferUndiseased();
		} else {
			o = .BestTargetInRange(pt, .range);
		}
		
		if(o.IsAlive && .IsValidTarget(o))
		if(.DistTo(o) < .min_range){
			
			Sleep(rand(400) + 500);
				
			if(!.AsHero.IsValid)
				.Face(o.posRH);
					
			if(rand(3) == 1){
				.Taunt(2000);
			}
		}
		while( o.IsAlive && .IsValidTarget(o) && (.IsVisible || sneakMode) && (.DistTo(o) > .min_range )){
			bSleeped = false;
			
			if(o.IsAlive)
			if(.DistTo(o) > .min_range)
			while(.Attack(o)){
			
                if(.IsAlive)
				if(o.AsUnit.IsAlive)
				if(.DistTo(o) > .min_range){
					if(!.IsVisible && !sneakMode) break;
					if(o.AsUnit.IsHeirOf("RamUnit")) break;
					bSleeped = true;
					
					//if(possibleSpeed)
						//if(.speed_factor < 100)
							//.SetSpeedFactor(100);
							
					// ######## MODUL UNIT SPEED START ##############
					
					if(k > 1)
					if(possibleSpeed){
						k = 0;		
						per_health = (.health+1)*100/(.maxhealth+1);

						per_stamina = (.stamina+1)*100/(.maxstamina+1);
						
						min = MIN(per_health, per_stamina);
						
						if(min < 80){
							if(min > 50) { min = 50; 
							} else if(min < 30) { min = 30; 
							} else { min = 40; }
							
							if(.speed_factor != min)
								.SetSpeedFactor(min);
								
						} else {
							if(.speed_factor < 100)                                  
								.SetSpeedFactor(100);
						} 
					}
					k+=1;
					
					// ######## MODUL UNIT SPEED END ##############
					// ######## MODUL SHIP 1 START ##############
					if(.IsHeirOf("ShipBattle")){
						if(.stamina >= 1)
							.SetStamina(.stamina - 1);
								
						if(.stamina <= 0)
							Sleep(10000);
						continue;
					}
					// ######## MODUL SHIP 1 END ################
					if(o.AsUnit.IsHeirOf("EGuardian")){
						if(o.AsUnit.command != "engage" &&
						   o.AsUnit.command != "engage_unit_type"){
						   
							if(rand(100) > 10){
								if(!o.AsUnit.BestTargetForPos.IsValid)
								if(o.AsUnit.health < o.AsUnit.maxhealth){
									//o.AsUnit.Heal(.attack-1);
									o.AsUnit.Heal(500);
								}
							}
						}
					}
					
					if(.HasSpecial(curse)){
						if(!o.AsUnit.IsCursed){
							if(.stamina >= csc){
								if(.IsAlive)
									if(o.AsUnit.IsAlive){
										.SetStamina(.stamina - csc); // curse_stamina_cost
										o.AsUnit.Curse();
									}
							}
						}
					}
					if(!IsAIPlayer(.player)){
						olBall = Intersect(ObjsInCircle(.pos, bc, "Military"), ClassPlayerObjs("Military", .player)).GetObjList; 
						if(olBall.count >= 2){
							Sleep(olBall.count*1000);
							continue;
						}
					}
					// ######## MODUL FORMATION 1 START ################
					if(!o.AsUnit.IsHeirOf("ShortRanged")){
						if(o.AsUnit.hero.IsValid)
							if(o.AsUnit.hero.formation == "Loose"){
								Sleep(1000+rand(50));
							}
					}
					// ######## MODUL FORMATION 1 END ################
				}
			}
			
			if(!bSleeped) Sleep(rand(100)+50);
			
			if(.IsHeirOf("EChariot") && .stamina >= disease_cost){
				o = .BestTargetInSquadSight_PreferUndiseased();
			} else {
				o = .BestTargetInRange(pt, .range);
			}
		}
		
	} else if(!.IsRanged){
        range = 90;
		
		if(.hero.IsValid){
			//if(.hero.army.count < 50)
			i = 50 - .hero.army.count;
			range += i;
		}

		o = .BestTargetInSquadSight();
		
		if(o.IsAlive && .IsValidTarget(o) && (.IsVisible || sneakMode) && (.DistTo(o) > .min_range)){
			if(!o.IsHeirOf("BaseAnimal")){
			Sleep(rand(400) + 30);
				if(!.AsHero.IsValid)
					.Face(o.posRH);
				
				if(rand(6) == 1){
					.Taunt(2000);
				}
			}
		}
		o = .BestTargetInRange(pt, range);
		
		while(o.IsAlive && .IsValidTarget(o) && (.IsVisible || sneakMode) && (.DistTo(o) > .min_range)){
			bSleeped = false;
			
			if(!.IsHeirOf("Piked")){
				while(!.GotoAttack(o, 1500, true, 15000)){
				
					bSleeped = true;
					
					o = .BestTargetInRange(pt, range);
					
					if(!o.IsAlive || ! .IsValidTarget(o) || (.DistTo(o) < .min_range)) break;
					
					if(!.IsVisible && !sneakMode) break; 
				}
			}
			if(o.IsAlive && .IsValidTarget(o) && (.IsVisible || sneakMode) && (.DistTo(o) > .min_range)){
				
				if(.IsHeirOf("Horse") && o.AsCatapult.IsHeirOf("Catapult")){
					Sleep(rand(500)+500);
					continue;
				}
				while(.Attack(o)){
					if(.IsAlive)
					if(o.AsUnit.IsAlive)
					if(.DistTo(o) > .min_range){
		
						if(!.IsVisible && !sneakMode) break;
						bSleeped = true;
						// ######## MODUL UNIT SPEED START ##############
						
						if(k > 1)
						if(possibleSpeed){
							k = 0;
							per_health = (.health+1)*100/(.maxhealth+1);

							per_stamina = (.stamina+1)*100/(.maxstamina+1);
							
							min = MIN(per_health, per_stamina);
							
							if(min < 80){
								if(min > 50) { min = 50; 
								} else if(min < 30) { min = 30; 
								} else { min = 40; }
								
								if(.speed_factor != min)
									.SetSpeedFactor(min);
									
							} else {
								if(.speed_factor < 100)                                  
									.SetSpeedFactor(100);
							}
						}
						k+=1;
						
						// ######## MODUL UNIT SPEED END ##############
						if(.HasSpecial(curse)){
							if(!o.AsUnit.IsCursed){
								if(.stamina >= csc){
									if(.IsAlive)
										if(o.AsUnit.IsAlive){
											.SetStamina(.stamina - csc); // curse_stamina_cost
											o.AsUnit.Curse();
										}
								}
							}
						}
					}
				}
			}
			if(!bSleeped) Sleep(rand(100)+50);
			
			o = .BestTargetInRange(pt, range);
		}
	}
	if(!o.IsAlive && (pt.x != .posRH.x || pt.y != .posRH.y)){
		while(!.Goto(pt, 0, 2000, false, -1));
	
	} else {
		.Idle(2000+j);
	}
	Sleep(rand(100)+100);
	if(possibleSpeed)
		if(.speed_factor < 100)                                  
			.SetSpeedFactor(100);
}
